package talent.service.impl;


import org.springframework.beans.factory.annotation.Autowired;
import talent.dto.RecommendationRequestDTO;
import talent.dto.StudentActivityRequestDTO;
import talent.dto.TalentQueryDTO;
import talent.entity.Talent;
import talent.exception.TalentNotFoundException;
import talent.repository.TalentRepository;
import talent.service.TalentService;
import talent.util.KMeansPlusPlusUtil;
import talent.util.ScoreCalculator;
import talent.vo.RecommendationVO;
import talent.vo.TalentVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class TalentServiceImpl implements TalentService {

    private final TalentRepository talentRepository;
    private final KMeansPlusPlusUtil kMeansPlusPlusUtil;
    private final ScoreCalculator scoreCalculator;

    @Override
    public List<RecommendationVO> recommendTalents(TalentQueryDTO queryDTO) {
        // 1. 根据查询条件获取符合基本要求的人才列表
        List<Talent> talents = talentRepository.findByCriteria(
                queryDTO.getSkillLevel(),
                queryDTO.getExperienceLevel(),
                queryDTO.getEducationLevel()
        );

        // 2. 计算每个人才的活跃度，并过滤掉活跃度低于60分的人才
        talents = talents.stream()
                .filter(t -> calculateActivityScore(t) >= 60) // 过滤活跃度低于60分的人才
                .collect(Collectors.toList());

        // 3. 使用k-means++算法对人才进行聚类，这里聚成4类
        List<List<Talent>> clusters = kMeansPlusPlusUtil.clusterTalents(talents, 4);

        // 4. 从每个聚类中挑选活跃度最高的3个人才
        List<Talent> activeTalents = clusters.stream()
                .flatMap(cluster -> cluster.stream()
                        .sorted(Comparator.comparing(this::calculateActivityScore).reversed())
                        .limit(3))
                .collect(Collectors.toList());

        // 5. 计算每个候选人的匹配度和价值评分，并生成推荐理由
        //    最后返回价值评分最高的前10个推荐结果
        return activeTalents.stream()
                .map(talent -> createRecommendationVO(talent, queryDTO))
                .sorted(Comparator.comparing(RecommendationVO::getValueScore).reversed())
                .limit(10)
                .collect(Collectors.toList());
    }

    @Override
    public List<TalentVO> findOptimalTalents(RecommendationRequestDTO requestDTO) {
        // 根据查询条件获取符合基本要求的人才列表
        List<Talent> talents = talentRepository.findByCriteria(
                requestDTO.getSkillLevel(),
                requestDTO.getExperienceLevel(),
                requestDTO.getEducationLevel()
        );

        // 使用k-means++算法找出在薪资限制下价值最高的候选人组合
        List<TalentVO> collect = kMeansPlusPlusUtil.findOptimalTalents(
                        talents,
                        requestDTO.getMaxSalary(),
                        requestDTO.getExpectedCount()
                ).stream()
                .map(this::convertToVO) // 将实体转换为VO对象
                .collect(Collectors.toList());
        return collect;
    }

    // 实现接口要求的获取人才详情方法
    @Override
    public TalentVO getTalentDetails(Long id) {
        // 从数据库中获取人才详情，如果不存在则抛出异常
        Optional<Talent> talentOptional = talentRepository.findTalentById(id);
        Talent talent = talentOptional.orElseThrow(() -> new TalentNotFoundException("人才ID不存在: " + id));

        // 将实体转换为VO对象并返回
        return convertToVO(talent);
    }


    @Override
    public List<TalentVO> getTopTenStudents() {
        // 获取所有学生信息
        List<Talent> talents = talentRepository.findAll();

        // 计算每个学生的综合评分
        List<TalentVO> studentVOs = talents.stream()
                .map(this::convertToStudentVO)
                .collect(Collectors.toList());

        // 按综合评分降序排序
        studentVOs.sort((a, b) -> Double.compare(b.getCompositeScore(), a.getCompositeScore()));

        // 返回评分最高的前十个学生（最多10个）
        return studentVOs.stream()
                .limit(10)
                .collect(Collectors.toList());
    }

    private TalentVO convertToStudentVO(Talent talent) {
        TalentVO vo = new TalentVO();
        vo.setId(talent.getId());
        vo.setName(talent.getName());
        vo.setGender(String.valueOf(talent.getGender()));
        vo.setAvatar(talent.getAvatar());
        vo.setPhone(talent.getPhone());
        vo.setSoftwareUsageDuration(talent.getSoftwareUsageDuration());
        vo.setVideoLearningDuration(talent.getVideoLearningDuration());
        vo.setPlanCompletionRate(talent.getPlanCompletionRate());
        vo.setUpdatedAt(talent.getUpdatedAt());

        // 计算综合评分
        vo.setCompositeScore(scoreCalculator.calculateCompositeScore(talent));

        return vo;
    }


//    @Override
//    public List<TalentVO> getTopActiveStudents(StudentActivityRequestDTO requestDTO) {
//        // 从数据库中获取指定年级的学生
//        List<Talent> students = talentRepository.findByGrade(requestDTO.getGrade());
//
//        // 计算每个学生的活跃度并筛选活跃度最高的学生
//        List<TalentVO> activeStudents = students.stream()
//                .map(this::convertToVO)
//                .sorted((a, b) -> Double.compare(b.getActiveScore(), a.getActiveScore()))
//                .limit(requestDTO.getPageSize() * requestDTO.getPageNum())
//                .collect(Collectors.toList());
//
//        // 分页
//        int start = (requestDTO.getPageNum() - 1) * requestDTO.getPageSize();
//        int end = Math.min(start + requestDTO.getPageSize(), activeStudents.size());
//
//        return activeStudents.subList(start, end);
//    }





    // 将Talent实体转换为TalentVO对象
    private TalentVO convertToVO(Talent talent) {
        TalentVO vo = new TalentVO();
        vo.setId(talent.getId());
        vo.setName(talent.getName());
        vo.setGender(talent.getGender().name()); // 将枚举转换为字符串
        vo.setBirthDate(talent.getBirthDate());
        vo.setPhone(talent.getPhone());
        vo.setAvatar(talent.getAvatar());
        vo.setEducationLevel(talent.getEducationLevel());
        vo.setProjectCount(talent.getProjectCount());
        vo.setWorkExperience(talent.getWorkExperience());
        vo.setUniversity(talent.getUniversity());
        vo.setMajor(talent.getMajor());
        vo.setSkills(talent.getSkills());
        vo.setAwards(talent.getAwards());
        vo.setDesiredPosition(talent.getDesiredPosition());
        vo.setExpectedSalary(talent.getExpectedSalary());
        vo.setLastLogin(talent.getLastLogin());
        vo.setPostsCount(talent.getPostsCount());
        vo.setVideoLearningDuration(talent.getVideoLearningDuration());
        vo.setSoftwareUsageDuration(talent.getSoftwareUsageDuration());
        vo.setPlanCompletionRate(talent.getPlanCompletionRate());
        vo.setCreatedAt(talent.getCreatedAt());
        vo.setUpdatedAt(talent.getUpdatedAt());
        return vo;
    }

    // 计算人才的活跃度评分（范围：0-100）
    private double calculateActivityScore(Talent talent) {
        double score = 0;

        // 最近登录时间（30天内得满分）
        long daysSinceLogin = java.time.temporal.ChronoUnit.DAYS.between(
                talent.getLastLogin().toLocalDate(),
                java.time.LocalDate.now()
        );
        if (daysSinceLogin <= 7) score += 30;
        else if (daysSinceLogin <= 30) score += 20;
        else if (daysSinceLogin <= 90) score += 10;

        // 发布稿子数量
        if (talent.getPostsCount() >= 10) score += 20;
        else if (talent.getPostsCount() >= 5) score += 15;
        else if (talent.getPostsCount() >= 1) score += 10;

        // 学习视频时长
        if (talent.getVideoLearningDuration() >= 1000) score += 20;
        else if (talent.getVideoLearningDuration() >= 500) score += 15;
        else if (talent.getVideoLearningDuration() >= 100) score += 10;

        // 软件使用时长
        if (talent.getSoftwareUsageDuration() >= 500) score += 20;
        else if (talent.getSoftwareUsageDuration() >= 200) score += 15;
        else if (talent.getSoftwareUsageDuration() >= 50) score += 10;

        // 计划完成率（假设planCompletionRate是一个百分比值，例如0.85表示85%）
        score += talent.getPlanCompletionRate() * 0.1;

        return Math.min(100, score); // 限制最高分为100分
    }

    // 创建推荐结果对象
    private RecommendationVO createRecommendationVO(Talent talent, TalentQueryDTO queryDTO) {
        RecommendationVO vo = new RecommendationVO();
        vo.setCandidateId(talent.getId());
        vo.setCandidateName(talent.getName());
        vo.setSkillScore(talent.getProjectCount());
        vo.setExperienceScore(talent.getWorkExperience());
        vo.setEducationScore(talent.getEducationLevel());
        vo.setSalaryRequirement(talent.getExpectedSalary());

        // 计算候选人的匹配度
        double matchScore = calculateMatchScore(talent, queryDTO);
        vo.setMatchPercentage(matchScore);

        // 计算候选人的价值评分
        double valueScore = calculateValueScore(talent);
        vo.setValueScore(valueScore);

        // 生成推荐理由
        String reason = generateRecommendationReason(talent, queryDTO);
        vo.setRecommendationReason(reason);

        return vo;
    }

    // 计算人才与职位要求的匹配度（百分比）
    private double calculateMatchScore(Talent talent, TalentQueryDTO queryDTO) {
        // 计算技能匹配度（项目数量作为技能水平的代理变量）
        double skillMatch = 1 - Math.abs(talent.getProjectCount() - queryDTO.getSkillLevel()) / 3.0;
        // 计算经验匹配度
        double expMatch = 1 - Math.abs(talent.getWorkExperience() - queryDTO.getExperienceLevel()) / 8.0;
        // 计算教育背景匹配度
        double eduMatch = 1 - Math.abs(talent.getEducationLevel() - queryDTO.getEducationLevel()) / 6.0;
        // 综合计算匹配度（技能权重40%，经验30%，教育背景30%）
        return (skillMatch * 0.4 + expMatch * 0.3 + eduMatch * 0.3) * 100;
    }

    // 计算人才的价值评分
    private double calculateValueScore(Talent talent) {
        // 综合项目数量、工作经验、教育背景和薪资期望来计算价值评分
        return talent.getProjectCount() * 0.3 +
                talent.getWorkExperience() * 0.2 +
                talent.getEducationLevel() * 0.1 +
                (1 - talent.getExpectedSalary() / 30000.0) * 0.4;
    }

    // 生成推荐理由
    private String generateRecommendationReason(Talent talent, TalentQueryDTO queryDTO) {
        StringBuilder reason = new StringBuilder();

        // 技能匹配度部分
        boolean skillMatched = talent.getProjectCount() >= queryDTO.getSkillLevel();
        reason.append("技能匹配度：");
        reason.append(skillMatched ?
                "该候选人的技能水平达到或超过了岗位要求，能够熟练应对岗位所需的技术挑战。" :
                "该候选人的技能水平与岗位要求有差距，但仍具备一定的相关能力，可能需要进一步培训或学习。");

        // 经验匹配度部分
        boolean experienceMatched = talent.getWorkExperience() >= queryDTO.getExperienceLevel();
        reason.append(" 经验匹配度：");
        reason.append(experienceMatched ?
                "经验丰富，能够快速适应岗位并做出贡献。" :
                "经验稍有不足，但具有较强的学习能力和成长潜力。");

        // 教育背景匹配度部分
        boolean educationMatched = talent.getEducationLevel() >= queryDTO.getEducationLevel();
        reason.append(" 教育背景匹配度：");
        reason.append(educationMatched ?
                "教育背景符合岗位要求，表明候选人具备扎实的理论基础。" :
                "教育背景与岗位要求略有差距，但通过实际工作经验弥补了这一不足。");

        // 薪资匹配度部分
        reason.append(" 薪资匹配度：");
        if (queryDTO.getMaxSalary() != null && talent.getExpectedSalary() <= queryDTO.getMaxSalary() * 0.8) {
            reason.append("候选人期望薪资低于企业可支出上限，具有较高的性价比。");
        } else {
            reason.append("候选人期望薪资接近企业可支出上限，需综合评估其技能和经验是否值得该薪资水平。");
        }

        return reason.toString();
    }

    // 将TalentVO对象转换为另一个TalentVO对象（这个方法看起来可能是重复的，需要检查是否必要）
    private TalentVO convertToVO(TalentVO talent) {
        TalentVO vo = new TalentVO();
        vo.setId(talent.getId());
        vo.setName(talent.getName());
        vo.setGender(talent.getGender());
        vo.setBirthDate(talent.getBirthDate());
        vo.setPhone(talent.getPhone());
        vo.setAvatar(talent.getAvatar());
        vo.setEducationLevel(talent.getEducationLevel());
        vo.setProjectCount(talent.getProjectCount());
        vo.setWorkExperience(talent.getWorkExperience());
        vo.setUniversity(talent.getUniversity());
        vo.setMajor(talent.getMajor());
        vo.setSkills(talent.getSkills());
        vo.setAwards(talent.getAwards());
        vo.setDesiredPosition(talent.getDesiredPosition());
        vo.setExpectedSalary(talent.getExpectedSalary());
        vo.setLastLogin(talent.getLastLogin());
        vo.setPostsCount(talent.getPostsCount());
        vo.setVideoLearningDuration(talent.getVideoLearningDuration());
        vo.setSoftwareUsageDuration(talent.getSoftwareUsageDuration());
        vo.setPlanCompletionRate(talent.getPlanCompletionRate());
        vo.setRankingScore(talent.getRankingScore());

        // 计算并设置活跃度评分
//        vo.setActiveScore(calculateActivityScore(talent));

        return vo;
    }
}
//        ### 功能概述
//
//  * **人才推荐** ：根据输入的查询条件（技能水平、经验水平、教育背景），从数据库中筛选符合条件的人才，计算他们的活跃度并过滤活跃度较低的人才。接着使用k-means++算法对人才进行聚类，从每个聚类中挑选活跃度高的候选人，最后计算这些候选人的匹配度和价值评分，并生成推荐理由，返回价值评分最高的前10个推荐结果。
//        * **最优人才查找** ：根据输入的查询条件、最大薪资和期望招聘人数，找出在薪资限制下价值最高的候选人组合。
//        * **人才详情获取** ：根据人才ID获取人才的详细信息。
//
//        ### 方法详解
//
//  * **recommendTalents** ：核心推荐方法，执行整个推荐流程，包括筛选、聚类和排序。
//        * **findOptimalTalents** ：利用k-means++算法找出最优人才组合。
//        * **getTalentDetails** ：获取指定人才的详细信息。
//        * **convertToVO** ：将实体对象转换为VO（Value Object）对象，用于数据传输。
//        * **calculateActivityScore** ：计算人才的活跃度评分，基于最近登录时间、发布稿子数量、学习视频时长、软件使用时长和计划完成率等因素。
//        * **createRecommendationVO** ：创建推荐结果对象，包含候选人的基本信息、匹配度、价值评分和推荐理由。
//        * **calculateMatchScore** ：计算人才与职位要求的匹配度，基于技能、经验和教育背景的综合评估。
//        * **calculateValueScore** ：计算人才的价值评分，综合考虑项目数量、工作经验、教育背景和薪资期望。
//        * **generateRecommendationReason** ：生成推荐理由，包括技能匹配度、经验匹配度、教育背景匹配度和薪资匹配度的详细描述。
//
//这段代码通过多种算法和计算方法，旨在为企业提供精准、高效的人才推荐服务，帮助企业快速找到符合要求的优秀人才。